﻿// ChapterHelper.cpp: implementation of the CChapterHelper class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ChapterHelper.h"
#include "UnicodeText.h"
#include "SmallUtilz.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CChapterHelper::CChapterHelper()
{

}

CChapterHelper::~CChapterHelper()
{

}

// 0: 암것도 아님, 1:챕터, 2:챕터이름
int CChapterHelper::readOGMline(CString &cs, int &no, CString &value)
{
	//CHAPTER01=00:00:00.000
	//CHAPTER01NAME=

	if (cs.Left(7).Compare(_T("CHAPTER"))) return 0;
	cs.Delete(0, 7);

	TCHAR tc = cs.GetAt(0);
	if (!_istdigit(tc)) return 0;
	no = _ttoi(static_cast<LPCTSTR>(cs));
	cs.TrimLeft(_T("0123456789"));

	if (cs.IsEmpty()) return 0;
	if (cs.GetAt(0)==_TCHAR('=')) {
		value = cs.Mid(1, 12);
		
		return isValidTime(value)?1:0;
	} else if (!cs.Left(5).Compare(_T("NAME="))) {
		value = cs.Mid(5);
		return 2;
	}

	return 0;
}

//#define ISNUM(tc) ((((TCHAR)(tc))>=_TCHAR('0')) && (((TCHAR)(tc))<=_TCHAR('9')))

bool CChapterHelper::isValidTime(LPCTSTR lp)
{
	//00:00:00.000
	//012345678901
	
	//길이 체크 안 함
	//if (_tcslen(lp)<12) return false;
	return (
		_istdigit(lp[0]) &&
		_istdigit(lp[1]) &&
		(lp[2] == _TCHAR(':')) &&
		_istdigit(lp[3]) &&
		_istdigit(lp[4]) &&
		(lp[5] == _TCHAR(':')) &&
		_istdigit(lp[6]) &&
		_istdigit(lp[7]) &&
		((lp[8] == _TCHAR('.')) || (lp[8] == _TCHAR(','))) &&
		_istdigit(lp[9]) &&
		_istdigit(lp[10]) &&
		_istdigit(lp[11])
		);

}

const int CChapterHelper::ciMAXCHAPTERFILESIZE = 65536;

bool CChapterHelper::readOGMChapter(LPCTSTR ogm, CStringArray &csa)
{
	if (CSmallUtilz4iTrans::GetFileSize(ogm)>ciMAXCHAPTERFILESIZE) return false;

	CUnicodeText utext;
	if (!utext.bReadTextfile(ogm)) return false;
	
	//CHAPTER01=
	//CHAPTER01NAME=
	//이 두 가지 포맷 아니면 모두 버림
	
	//여기부터
	int max=-1;
	CString line, val;
	int pos=0, next, no;

	//개수 파악
	while (true) {
		int len = utext.iRead1Line(utext.tcText, utext.lLen, pos, next, line);
		if (len<0) break;

		pos = next;
		if (readOGMline(line, no, val)) {
			if (no>max) max=no;
		}
	}
	
	if (max<0) return false;

	// CStringArray에 일단 대입
	CStringArray csaTime, csaValue;
	csaTime.SetSize(max+1);
	csaValue.SetSize(max+1);
	pos=0;
	while (true) {
		int len = utext.iRead1Line(utext.tcText, utext.lLen, pos, next, line);
		if (len<0) break;
		
		pos = next;
		switch (readOGMline(line, no, val)) {
		case 1:
			csaTime.SetAt(no, val);
			break;

		case 2:
			csaValue.SetAt(no, val);
			break;
		}
	}

	//00:00:00.000
	//가나다
	// 이렇게 분리된 것을
	//000000000가나다
	// 형식으로 올림

	CString cs;
	csa.RemoveAll();
	for (int i=0; i<=max; i++) {
		cs = csaTime.GetAt(i);
		if (isValidTime(cs)) {
			cs = cs.Mid(0, 2)+cs.Mid(3, 2)+cs.Mid(6, 2)+cs.Mid(9, 3)+csaValue.GetAt(i);
			csa.Add(cs);
		}
	}

	return true;
}

bool CChapterHelper::readSrtChapter(LPCTSTR lpSrt, CStringArray &csa)
{
	UINT filesize = CSmallUtilz4iTrans::GetFileSize(lpSrt);
	if ((filesize<10) || (filesize>ciMAXCHAPTERFILESIZE)) return false;

	CUnicodeText utext;
	utext.bReadTextfile(lpSrt);

	//1
	//00:00:20,000 --> 00:00:24,400
	//자막내용
	//이거 찾아 삼만리

	long lTime = lFindTime(utext.tcText, utext.lLen, 0);
	csa.RemoveAll();
	
	while (lTime>=0) {
		CString csTime;
		for (int i=0; i<12; i++) {
			TCHAR tcDigit = utext.tcText[lTime+i];
			if (_istdigit(tcDigit))
				csTime += tcDigit;
		}
		
		lTime+=30;
		
		long lDblEnter = lFindDblEnter(utext.tcText, utext.lLen, lTime);
		int iContentSize = (lDblEnter>=0)?(iContentSize = lDblEnter-lTime):(iContentSize = utext.lLen-lTime);
		
		TCHAR *tcBuf = new TCHAR[iContentSize+1];
		memcpy(tcBuf, utext.tcText+lTime, iContentSize*sizeof(TCHAR));
		tcBuf[iContentSize] = _TCHAR(0);
		CString csName(tcBuf);
		delete []tcBuf;

		csName.TrimLeft();
		csName.TrimRight();
		int enterpos = csName.Find(_TCHAR('\r'));
		if (enterpos>=0) csName = csName.Left(enterpos);

		csa.Add(csTime+csName);

		if (lDblEnter>=0) {
			lTime = lFindTime(utext.tcText, utext.lLen, lDblEnter+2);
		} else {
			break;
		}
	}

	return (csa.GetSize()>0);
}

void CChapterHelper::insertTimeAscending(CStringArray &csa, LPCTSTR lp)
{
	for (int i=0; i<9; i++) {
		if (!_istdigit(lp[i])) return;
	}

	CString cs(lp);
	cs = cs.Left(9);
	int count = csa.GetSize();

	for (int i=0; i<count; i++) {
		CString cs0 = csa.GetAt(i).Left(9);
		int comp = cs.Compare(cs0);
		if (comp<=0) {
			if (comp) {
				csa.InsertAt(i, lp);
			}
			return;
		}
	}

	csa.Add(lp);
}

int CChapterHelper::timeStr2ms(LPCTSTR lp)
{
	//010101012
	//012345678
	for (int i=0; i<9; i++) {
		if (!_istdigit(lp[i])) return 0;
	}

	return CSmallUtilz4iTrans::tcTime2Int((TCHAR*)lp, false);
}

TCHAR * CChapterHelper::ms2TimeStr(int ms0)
{
	static TCHAR ret[10];
	int h, m, s, ms;
	CSmallUtilz4iTrans::ms2HMSMS(ms0, h, m, s, ms);
	_stprintf_s(ret, 10, _T("%02d%02d%02d%03d"), h, m, s, ms);
	return ret;
}

// duration 단위는 ms
// duration이 0 이하면 무조건 수용, 양수이면 그까지만 수용
bool CChapterHelper::writeSrtChapter(LPCTSTR lpSrt, CStringArray &csa, int duration)
{
	CStringArray csa0;
	int count = csa.GetSize(), i;

	if (count<1) return false;
	
	//ja:Chapter 류 정리
	//012345678ja:Chapter
	
	int colonPos = csa.GetAt(0).Find(_TCHAR(':'));
	bool colonUsable = true;
	for (i=1; i<count; i++) {
		if (colonPos != csa.GetAt(i).Find(_TCHAR(':'))) {
			colonUsable = false;
		}
	}

	if (colonUsable && (colonPos>=9)) {
		colonPos -= 8;
	} else {
		colonUsable = false;
	}

	for (i=0; i<count; i++) {
		CString cs = csa.GetAt(i);

		int now = timeStr2ms(cs);
		if ((duration<=0) || (now<=duration)) {
			insertTimeAscending(csa0, cs);
		}
	}

	insertTimeAscending(csa0, _T("000000000"));

	count = csa0.GetSize();
	if (duration<=0) {
		CString cs = csa0.GetAt(count-1);
		duration = timeStr2ms(cs)+1;
	}

	//1
	//00:00:20,000 --> 00:00:24,400
	//\r
	
	CString cs, cs0;
	
	if (count>1) {
		for (i=0; i<count; i++) {
			cs0.Format(_T("%d"), i+1);
			cs+=cs0;
			
			cs0 = csa0.GetAt(i);
			cs+=(_TCHAR('\r')+cs0.Left(2)+_TCHAR(':')+cs0.Mid(2, 2)+_TCHAR(':')+cs0.Mid(4, 2)+_TCHAR(',')+cs0.Mid(6, 3)+_T(" --> "));
			
			if (i<count-1) {
				cs0 = csa0.GetAt(i+1);
			} else {
				cs0 = ms2TimeStr(duration);
			}
			
			cs+=(cs0.Left(2)+_TCHAR(':')+cs0.Mid(2, 2)+_TCHAR(':')+cs0.Mid(4, 2)+_TCHAR(',')+cs0.Mid(6, 3)+_TCHAR('\r'));
			cs0 = csa0.GetAt(i).Mid(9);
			if (colonUsable) cs0.Delete(0, colonPos);
			if (cs0.GetLength()) cs+=(cs0 + _TCHAR('\r'));
			
			cs += _TCHAR('\r');
		}

		CUnicodeText utext;
		utext.lLen = cs.GetLength()+1;
		utext.tcText = new TCHAR[utext.lLen];
		_tcscpy_s(utext.tcText, utext.lLen, static_cast<LPCTSTR>(cs));
		utext.lLen = cs.GetLength();
		
		utext.WriteTextfile(lpSrt);

		return true;
	}

	return false;
}

